home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / netlib / lineread.c < prev    next >
Text File  |  1994-02-05  |  12KB  |  430 lines

  1. /*
  2.  * lineread.c
  3.  *
  4.  * Author: Tomi Ollila <too@cs.hut.fi>
  5.  *
  6.  * This module is FREEWARE. Standard "NO WARRANTY" disclaimer applies.
  7.  *
  8.  * Created: Thu Jul 12 16:40:03 EET 1990 too
  9.  * Last modified: Sat Feb  5 15:13:01 1994 too
  10.  *
  11.  * $Id: lineread.c,v 3.2 1994/02/05 13:00:45 too Exp $
  12.  *
  13.  * HISTORY
  14.  * $Log: lineread.c,v $
  15.  * Revision 3.2  1994/02/05  13:00:45  too
  16.  * Added charRead autodoc
  17.  *
  18.  * Revision 3.1  1994/02/03  19:22:31  ppessi
  19.  * Added autodoc
  20.  *
  21.  * Revision 1.3  1993/07/13  15:15:53  too
  22.  * Made lineread.c compile without <sys/cdefs.h> file
  23.  *
  24.  * Revision 1.1  1993/06/16  16:43:52  too
  25.  * Initial revision
  26.  */
  27.  
  28. /*
  29.  * since charRead is a macro package and having no `.c' -file, it's
  30.  * documentation is added here
  31.  */
  32.  
  33. /****** net.lib/charRead ****************************************************
  34. *
  35. *   NAME
  36. *       charRead -- read characters from socket one by one.
  37. *
  38. *   SYNOPSIS
  39. *       initCharRead(rc, fd)
  40. *
  41. *       void initCharRead(struct CharRead *, int);
  42. *
  43. *
  44. *       character = charRead(rc)
  45. *
  46. *       int charRead(struct CharRead *);
  47. *
  48. *
  49. *   DESCRIPTION
  50. *       charRead is a macro package which return characters one by one 
  51. *       from given socket input stream. The socket where data is to be read
  52. *       is set by calling initCharRead(): rc is the pointer to charread
  53. *       structure previously allocated. fd is the (socket) descriptor where
  54. *       reading is to be done.
  55. *
  56. *       charRead() returns the next character from input stream or one of
  57. *       the following:
  58. *
  59. *       RC_DO_SELECT    (-3)    - read input buffer is returned. Do select
  60. *                                 before next call if you don't want charread
  61. *                                 to block.
  62. *
  63. *       RC_EOF          (-2)    - end-of-file condition has occurred.
  64. *
  65. *       RC_ERROR        (-1)    - there has been an error while filling new
  66. *                                 charread buffer. Check the value of Errno()
  67. *
  68. *   NOTE
  69. *       Always use variable of type int to store return value from charRead()
  70. *       since the numeric value of characters returned may vary between
  71. *       0 -255 (or even greater). As you may know, -3 equals 253 if of type
  72. *       unsigned char.
  73. *
  74. *   EXAMPLE
  75. *       \*
  76. *        * This piece of code shows how to use charread with select()
  77. *        *\
  78. *       #include <sys/types.h>
  79. *       #include <sys/socket.h>
  80. *       #include <charread.h>
  81. *
  82. *       main_loop(int sock)
  83. *       {
  84. *         struct CharRead rc;
  85. *         fd_set readfds;
  86. *         int c;
  87. *
  88. *         initCharRead(&rc, sock);
  89. *
  90. *         FD_ZERO(&readfds);
  91. *
  92. *         while(1) {
  93. *           FD_SET(sock, &readfds);     
  94. *
  95. *           if (select(sock + 1. &readfds, NULL, NULL, NULL)) < 0) {
  96. *             perror("select");
  97. *             break;
  98. *           }
  99. *           if (FD_ISSET(sock, &readfds)) {
  100. *             while((c = charRead(&rc)) >= 0)
  101. *               handle_next_input_character(c);
  102. *             if (c == RC_EOF)
  103. *               break;
  104. *             if (c == RC_ERROR) {
  105. *               perror("charRead");
  106. *               break;
  107. *             }
  108. *           }
  109. *         }
  110. *       }
  111. *
  112. *    PORTABILITY
  113. *       The source file charread.h should be able to be used in 
  114. *       UNIX programs as is.
  115. *
  116. *    AUTHORS
  117. *       Tomi Ollila,
  118. *       the AmiTCP/IP Group <amitcp-group@hut.fi>,
  119. *
  120. *    SEE ALSO
  121. *       lineRead(), bsdsocket.library/recv()
  122. *****************************************************************************
  123. *
  124. */
  125.  
  126.  
  127. /****** net.lib/lineRead *****************************************************
  128.  
  129.     NAME
  130.         lineRead -- read newline terminated strings from socket
  131.  
  132.     SYNOPSIS
  133.         initLineRead(rl, fd, lftype, bufsize)
  134.  
  135.         void initLineRead(struct LineRead *, int, int, int);
  136.  
  137.  
  138.         length = lineRead(rl)
  139.  
  140.         int lineread(struct LineRead *);
  141.  
  142.  
  143.     FUNCTION
  144.         lineRead() reads newline terminated strings from given descriptor
  145.         very efficiently. All the options needed are set by calling
  146.         initLineRead(): rl is the pointer to lineread structure previously
  147.         allocated. fd is the (socket) descriptor where reading is to be
  148.         done. lftype can have following 3 values:
  149.  
  150.             RL_LFNOTREQ - Newline terminated strings are returned unless
  151.                           there is no newlines left in currently buffered
  152.                           input. In this case remaining buffer is returned.
  153.  
  154.             RL_LFREQLF  - If there is no newlines left in currently buffered
  155.                           input the remaining input data is copied at the
  156.                           start of buffer. Caller is informed that next
  157.                           call will fill the buffer (and it may block).
  158.                           Lines are always returned with newline at the end
  159.                           unless the string is longer than whole buffer.
  160.  
  161.             RL_LFREQNUL  - Like LF_REQLF, but remaining newline is removed.
  162.                           Note here that lenght is one longer that actual
  163.                           string length since line that has only one
  164.                           newline at the end would return length as 0
  165.                           which indigate string incomplete condition.
  166.  
  167.         bufsize is used to tell lineread how big the receive buffer is.
  168.         always put RL_BUFSIZE here since that value is used to determine
  169.         the memory allocated for the buffer. This option is given to you
  170.         so you may decide to use different buffer size than the default
  171.         1024.
  172.  
  173.         lineRead() returns the newline terminated string in rl_line field
  174.         of lineread structure. Return values of lineRead() are:
  175.  
  176.              1 - RL_BUFSIZE     - normal length of returned string.
  177.  
  178.              0                  - If zero is returned just after select(),
  179.                                   end-of-file condition has occurred.
  180.                                   Otherwise string is not completed yet.
  181.                                   Make sure you call select() (or use non-
  182.                                   blocking IO) if you don't want next call
  183.                                   to block.
  184.  
  185.             -1                  - if rl_Line field of lineread structure
  186.                                   is NULL, it indicates error condition.
  187.                                   If rl_Line points to start of string
  188.                                   buffer, input string has been longer
  189.                                   than buffer. In this case rl_Line points
  190.                                   to zero terminated string of length
  191.                                   RL_BUFSIZE.
  192.  
  193.         You may modify the zero terminated string returned by lineRead() in
  194.         any way, but memory around the string is private lineread memory.
  195.  
  196.     EXAMPLE
  197.         \*
  198.          * The following code shows how to use lineread with select()
  199.          *\
  200.         #ifdef USE_LOW_MEMORY_BUFFER
  201.         #define RL_BUFSIZE 256
  202.         #endif
  203.  
  204.         #include <sys/types.h>
  205.         #ifdef AMIGA
  206.         #include <bsdsocket.h>
  207.         #endif
  208.         #include <lineread.h>
  209.  
  210.         #define NULL 0
  211.  
  212.         ...
  213.  
  214.         main_loop(int sock)
  215.         {
  216.           struct LineRead * rl;
  217.           int length;
  218.           fd_set reafdfs;
  219.  
  220.           if (rl = (struct LineRead *)AllocMem(sizeof (*rl), 0)) {
  221.  
  222.             initLineRead(rl, sock, LF_REQLF, RL_BUFSIZE);
  223.  
  224.             FD_ZERO(&readfds);
  225.  
  226.             while(1) {
  227.               FD_SET(sock, &readfds);
  228.  
  229.               if (select(sock + 1, &readfds, NULL, NULL, NULL)) < 0) {
  230.                 perror("select");
  231.                 break;
  232.               }
  233.               if (FD_ISSET(sock, &readfds))
  234.                 if ((length = lineRead(rl)) == 0) \* EOF *\
  235.                   break;
  236.                 do {
  237.                   if (length > 0)
  238.                     write(1, rl->rl_Line, length); \* stdout. write() for *\
  239.                                                    \* speed demonstration *\
  240.                   else { \* length == -1 *\
  241.                     if (rl->rl_Line == NULL); {
  242.                       perror("lineRead");
  243.                       break;
  244.                     }
  245.                     else {
  246.                       fprintf(stderr, "lineread input buffer overflow!\n");
  247.                       write(1, rl->rl_Line, RL_BUFSIZE);
  248.                       write(1, "\n", 1);
  249.                     }
  250.                   }
  251.                 } while ((length = lineRead(rl)) != 0); \* 0 -> do select() *\
  252.             }
  253.           FreeMem(rl, sizeof (*rl);
  254.           }
  255.           else
  256.             fprintf("AllocMem: Out Of memory\n");
  257.         }
  258.  
  259.      PORTABILITY
  260.         The source modules lineread.c and lineread.h should compile
  261.         in UNIX machines as is.
  262.  
  263.      AUTHORS
  264.         Tomi Ollila,
  265.         the AmiTCP/IP Group <amitcp-group@hut.fi>,
  266.  
  267.      SEE ALSO
  268.         charRead(), bsdsocket.library/recv()
  269.  
  270. ******************************************************************************
  271. */
  272.  
  273. #include "lineread.h"
  274.  
  275. #ifdef AMIGA
  276. extern struct Library * SocketBase;
  277. #define READ(a, b, c) recv(a, b, c, 0)
  278. #if __SASC
  279. #include <proto/socket.h>
  280. #elif __GNUC__
  281. #include <inline/socket.h>
  282. #endif
  283. #else /* not AMIGA */
  284. #define READ(a, b, c) read(a, b, c)
  285. #endif /* AMIGA */
  286.  
  287. #ifndef NULL
  288. #define NULL 0
  289. #endif
  290.  
  291. #ifndef FALSE
  292. #define FALSE 0
  293. #endif
  294.  
  295. #ifndef TRUE
  296. #define TRUE 1
  297. #endif
  298.  
  299. #ifndef __CONCAT
  300. #if defined (__STDC__) || defined (__cplusplus)
  301. #define __CONCAT(x,y) x ## y
  302. #else
  303. #define __CONCAT(x,y) x/**/y
  304. #endif
  305. #endif /* __CONCAT not defined */  
  306.   
  307. #define RLP(field) __CONCAT(rl->rl_Private.rlp_,field)
  308.  
  309.  
  310. #if defined (__STDC__) || defined (__cplusplus)
  311.  
  312. int lineRead(struct LineRead * rl)
  313.  
  314. #else
  315.  
  316. int lineRead(rl)
  317.      struct LineRead * rl;
  318.  
  319. #endif
  320. {
  321.   int i;
  322.   
  323.   if (RLP(Bufpointer) == RLP(Howlong))
  324.  
  325.     if (RLP(Selected)) {
  326.  
  327.       if (RLP(Line_completed))
  328.     RLP(Startp) = RLP(Bufpointer) = 0;
  329.  
  330.       if ((i = READ(rl->rl_Fd,
  331.             RLP(Buffer) + RLP(Bufpointer),
  332.             RLP(Buffersize) - RLP(Bufpointer))) <= 0) {
  333.     /*
  334.      * here if end-of-file or on error. set Howlong == Bufpointer
  335.      * so if non-blocking I/O is in use next call will go to READ()
  336.      */
  337.     RLP(Howlong) = RLP(Bufpointer);
  338.     rl->rl_Line = NULL;            
  339.     return i;
  340.       }
  341.       else
  342.     RLP(Howlong) = RLP(Bufpointer) + i;
  343.     }
  344.     else /* Inform user that next call may block (unless select()ed) */ 
  345.       {
  346.     RLP(Selected) = TRUE;
  347.     return 0;
  348.       }
  349.   else /* Bufpointer has not reached Howlong yet. */
  350.     {
  351.       RLP(Buffer)[RLP(Bufpointer)] = RLP(Saved);
  352.       RLP(Startp) = RLP(Bufpointer);
  353.     }
  354.  
  355.   /*
  356.    * Scan read string for next newline.
  357.    */
  358.   while (RLP(Bufpointer) < RLP(Howlong))
  359.     if (RLP(Buffer)[RLP(Bufpointer)++] == '\n')
  360.       goto Skip;
  361.  
  362.   /*
  363.    * Here if Bufpointer == Howlong.
  364.    */
  365.   if (rl->rl_Lftype != RL_LFNOTREQ) {
  366.     RLP(Selected) = TRUE;
  367.  
  368.     if (RLP(Bufpointer) == RLP(Buffersize)) {
  369.       /*
  370.        * Here if Bufpointer reaches end-of-buffer.
  371.        */
  372.       if (RLP(Startp) == 0) { /* (buffer too short for whole string) */
  373.     RLP(Line_completed) = TRUE;
  374.     rl->rl_Line = RLP(Buffer);
  375.     RLP(Buffer)[RLP(Bufpointer)] = '\0';
  376.     return -1;
  377.       }
  378.       /*
  379.        * Copy partial string to start-of-buffer and make control ready for
  380.        * filling rest of buffer when next call to lineRead() is made
  381.        * (perhaps after select()).
  382.        */
  383.       for (i = 0; i < RLP(Buffersize) - RLP(Startp); i++)
  384.     RLP(Buffer)[i] = RLP(Buffer)[RLP(Startp) + i];
  385.       RLP(Howlong)-= RLP(Startp);
  386.       RLP(Bufpointer) = RLP(Howlong);
  387.       RLP(Startp) = 0;
  388.     }
  389.     
  390.     RLP(Line_completed) = FALSE;
  391.     return 0;
  392.   }
  393.  
  394.  Skip:
  395.   RLP(Line_completed) = TRUE;
  396.   if (rl->rl_Lftype == RL_LFREQNUL)
  397.     RLP(Buffer)[RLP(Bufpointer) - 1] = '\0';
  398.   RLP(Saved) = RLP(Buffer)[RLP(Bufpointer)];
  399.   RLP(Buffer)[RLP(Bufpointer)] = '\0';
  400.   RLP(Selected) = FALSE;
  401.   rl->rl_Line = RLP(Buffer) + RLP(Startp);
  402.  
  403.   return (RLP(Bufpointer) - RLP(Startp));
  404. }
  405.  
  406. #undef READ      
  407.  
  408. #if defined (__STDC__) || defined (__cplusplus)
  409.       
  410. void initLineRead(struct LineRead * rl, int fd, int lftype, int buffersize)
  411.       
  412. #else
  413.  
  414. int initLineRead(rl, fd, lftype, buffersize)
  415.       struct LineRead * rl;
  416.       int fd;
  417.       int lftype;
  418.       int buffersize;
  419.   
  420. #endif
  421. {      
  422.   rl->rl_Fd     = fd;
  423.   rl->rl_Lftype = lftype;
  424.  
  425.   RLP(Bufpointer) = RLP(Howlong) = 0;
  426.   RLP(Selected) = RLP(Line_completed) = TRUE;
  427.  
  428.   RLP(Buffersize) = buffersize;
  429. }
  430.